/**
 * 淹没分析类
 * 用于在Cesium中模拟洪水淹没效果，支持水位上升和下降动画
 * @author rawcloud
 * @class SubmergenceAnalysis
 * @description 提供淹没区域的可视化和动态水位变化控制
 * 示例：
 * const submergenceAnalysis = new SubmergenceAnalysis({
 *     viewer: viewer,
 *     targetHeight: 10,
 *     startHeight: 0,
 *     adapCoordi: [114.314521, 22.620386, 114.314521, 22.620386, 114.314521, 22.620386],
 *     speed: 1,
 *     color: Cesium.Color.fromBytes(64, 157, 253, 100),
 *     changetype: 'up',
 *     speedCallback: function (h) {
 *         console.log('当前水位：' + h);
 *     },
 *     endCallback: function () {
 *         console.log('水位变化完成');
 *     }
 * });
 */
import * as Cesium from 'cesium'
class SubmergenceAnalysis {
    /**
     * 构造函数，初始化淹没分析实例
     * 
     * @param {Object} option - 配置选项对象
     * @param {Cesium.Viewer} option.viewer - Cesium Viewer实例
     * @param {number} [option.targetHeight=10] - 目标淹没高度
     * @param {number} [option.startHeight=0] - 起始淹没高度
     * @param {number} [option.waterHeight=startHeight] - 当前水位高度
     * @param {Array<number>} [option.adapCoordi=[0,0,0,0,0,0]] - 淹没范围坐标数组，格式：[lon1,lat1,lon2,lat2,...]
     * @param {number} [option.speed=1] - 水位变化速度
     * @param {Cesium.Color} [option.color=new Cesium.Color.fromBytes(64,157,253,100)] - 淹没区域颜色
     * @param {string} [option.changetype='up'] - 水位变化类型：'up'上升/'down'下降
     * @param {Function} [option.speedCallback=function(h){}] - 水位变化回调函数
     * @param {Function} [option.endCallback=function(){}] - 水位达到目标后的回调函数
     */
    constructor(option) {
        // 初始化配置参数
        this.viewer = option.viewer;                        // Cesium Viewer实例
        this.targetHeight = option.targetHeight || 10;     // 目标淹没高度
        this.startHeight = option.startHeight || 0;        // 起始淹没高度
        this.waterHeight = option.waterHeight !== undefined ? option.waterHeight : this.startHeight; // 当前水位
        this.adapCoordi = option.adapCoordi || [0, 0, 0, 0, 0, 0]; // 淹没范围坐标
        this.speed = option.speed || 1;                    // 水位变化速度
        this.color = option.color || new Cesium.Color.fromBytes(64, 157, 253, 100); // 淹没区域颜色
        this.changetype = option.changetype || 'up';       // 水位变化类型
        this.speedCallback = option.speedCallback || function (h) {}; // 水位变化回调
        this.endCallback = option.endCallback || function () {};       // 结束回调
        
        // 初始化内部状态
        this.polygonEntity = null;                         // 存储多边形实体
        this.timer = null;                                 // 定时器引用
        
        // 如果提供了viewer，则创建实体并更新多边形
        if (this.viewer) {
            this.createEntity();
            this.updatePoly(this.adapCoordi);
        }
    }
    /**
     * 创建淹没可视化实体
     * 移除已存在的淹没实体并创建新的多边形实体用于显示淹没区域
     * 使用CallbackProperty动态更新高度，实现水位变化的动画效果
     */
    createEntity() {
        // 移除已存在的淹没实体（如果有）
        if (this.polygonEntity && this.polygonEntity.length > 0) {
            for (let entity of this.polygonEntity) {
                this.viewer.entities.remove(entity);
            }
        }
        
        // 初始化实体数组
        this.polygonEntity = [];
        
        // 创建新的多边形实体
        let nEntity = this.viewer.entities.add({
            polygon: {
                hierarchy: {},                     // 多边形层级，稍后会更新
                material: this.color,              // 使用配置的颜色
                // perPositionHeight: true         // 注释掉的选项，用于基于位置高度的显示
            }
        });
        
        // 设置动态高度，使用CallbackProperty实现实时更新
        nEntity.polygon.extrudedHeight = new Cesium.CallbackProperty(() => this.waterHeight, false);
        
        // 添加到实体数组
        this.polygonEntity.push(nEntity);
    }
    /**
     * 更新淹没区域的多边形范围
     * 转换输入坐标并应用到多边形实体上，更新淹没区域的显示范围
     * 
     * @param {Array<number>|Array<Object>} adapCoordi - 淹没范围坐标
     * 支持格式：
     * - 数字数组：[lon1,lat1,lon2,lat2,...]
     * - 对象数组：[{lng,lat}, {lng,lat}, ...] 或 [{x,y}, {x,y}, ...]
     */
    updatePoly(adapCoordi) {
        // 转换坐标格式为Cesium可用的格式
        this.adapCoordi = this.coordsTransformation(adapCoordi);
        
        // 如果多边形实体已创建，则更新其层级数据
        if (this.polygonEntity && this.polygonEntity.length > 0) {
            this.polygonEntity[0].polygon.hierarchy = new Cesium.PolygonHierarchy(
                this.adapCoordi // 使用转换后的坐标数组
            );
        }
    }
    /**
     * 坐标转换方法
     * 将各种格式的坐标数组转换为Cesium可识别的Cartesian3坐标数组
     * 
     * @param {Array<number>|Array<Object>} coords - 输入坐标
     * @returns {Array<Cesium.Cartesian3>} 转换后的Cartesian3坐标数组
     */
    coordsTransformation(coords) {
        var c = [];
        
        // 处理数字数组格式 [lon1,lat1,lon2,lat2,...]
        if (typeof coords[0] == "number" && typeof coords[1] == "number") {
            // 判断是否为经纬度坐标（在合理范围内）
            if (coords[0] < 180 && coords[0] > -180 && coords[1] < 90 && coords[1] > -90) {
                // 使用经纬度数组创建Cartesian3数组
                c = Cesium.Cartesian3.fromDegreesArray(coords);
            } else {
                // 直接从数字数组创建Cartesian3数组
                c = Cesium.Cartesian3.fromArray(coords);
            }
        } 
        // 处理对象数组格式 [{lng,lat}, ...] 或 [{x,y}, ...]
        else {
            for (var i = 0; i < coords.length; i++) {
                var point = coords[i];
                var p = null;
                
                // 处理 {lng,lat} 格式
                if (point.lng) {
                    p = Cesium.Cartesian3.fromDegrees(point.lng, point.lat);
                }
                // 处理 {x,y} 格式
                else if (point.x) {
                    // 判断是否为经纬度坐标
                    if (point.x < 180 && point.x > -180 && point.y < 90 && point.y > -90) {
                        // 修复：使用正确的x,y属性
                        p = Cesium.Cartesian3.fromDegrees(point.x, point.y);
                    } else {
                        // 直接使用现有坐标
                        p = point;
                    }
                }
                
                if (p) {
                    c.push(p);
                }
            }
        }
        
        return c;
    }

    /**
     * 启动淹没动画
     * 创建定时器来动态更新水位高度，实现洪水上升或下降的动画效果
     * 当水位达到目标高度时，停止动画并触发结束回调
     */
    start() {
        // 创建定时器，每20ms更新一次水位
        this.timer = window.setInterval(() => {
            // 计算实际移动步长
            var sp = this.speed / 50;
            
            // 根据变化类型更新水位高度
            if (this.changetype == "up") {
                // 水位上升逻辑
                // 使用简单加法替代未导入的util.floatObj.add
                this.waterHeight += sp;
                
                // 检查是否达到目标高度
                if (this.waterHeight > this.targetHeight) {
                    this.waterHeight = this.targetHeight; // 设置为目标高度
                    window.clearInterval(this.timer);     // 清除定时器
                    this.endCallback();                   // 触发结束回调
                }
            } else {
                // 水位下降逻辑
                this.waterHeight -= sp;
                
                // 检查是否达到目标高度
                if (this.waterHeight < this.targetHeight) {
                    this.waterHeight = this.targetHeight; // 设置为目标高度
                    window.clearInterval(this.timer);     // 清除定时器
                    this.endCallback();                   // 触发结束回调
                }
            }
            
            // 触发水位变化回调，提供当前水位高度
            this.speedCallback(this.waterHeight);
        }, 20); // 20ms的更新频率
    }
    /**
     * 清理淹没分析实例
     * 停止动画定时器，移除所有实体，重置水位高度
     */
    /**
     * 暂停淹没动画
     * 停止定时器但保留当前水位高度和实体，实现动画暂停功能
     */
    stop() {
        // 停止动画定时器（如果存在）
        if (this.timer) {
            window.clearInterval(this.timer);
            this.timer = null;
        }
    }

    /**
     * 清理淹没分析实例
     * 停止动画定时器，移除所有实体，重置水位高度
     */
    clear() {
        let viewer = this.viewer;
        
        // 停止动画定时器（如果存在）
        if (this.timer) {
            window.clearInterval(this.timer);
            this.timer = null;
        }
        
        // 重置水位高度到起始值
        this.waterHeight = this.startHeight;
        
        // 移除所有淹没实体
        if (this.polygonEntity && this.polygonEntity.length > 0) {
            for (let entity of this.polygonEntity) {
                viewer.entities.remove(entity);
            }
        }
        
        // 清空实体引用
        this.polygonEntity = null;
    }
}

// 导出SubmergenceAnalysis类供其他模块使用
export default SubmergenceAnalysis;